package com.cn.common.utils.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator.Builder;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.cn.common.cache.LocalCache;
import com.cn.common.model.AuthUser;
import com.cn.common.utils.exception.AssertUtil;
import com.cn.common.utils.exception.ServiceException;
import com.cn.common.utils.http.CookieUtil;
import com.cn.common.utils.text.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtil {
    private static final Logger log = LoggerFactory.getLogger(JwtUtil.class);

    //过期时间设置(24h)
    private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
    private static int TOKEN_EMPTY = 1012;
    private static int TOKEN_INVALID = 1010;
    private static String TOKEN_EMPTY_MSG = "token为空";
    private static String TOKEN_INVALID_MSG = "token验证失败，请重新登录";
    private static String ssosecret = "#12345D";

    public JwtUtil() {
    }

    public static boolean verify(String token, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
            return true;
        } catch (Exception var5) {
            return false;
        }
    }

    public static String getSubject(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getSubject();
        } catch (JWTDecodeException var2) {
            return null;
        }
    }

    public static String getValue(String token, String key) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(key).asString();
        } catch (JWTDecodeException var3) {
            return null;
        }
    }

    public static Map<String, String> verifyToken(String token, String secret) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);
        Map<String, Claim> map = jwt.getClaims();
        Map<String, String> resultMap = new HashMap(map.size());
        map.forEach((k, v) -> {
            String var10000 = (String)resultMap.put(k, v.asString());
        });
        return resultMap;
    }

    public static String getValue(String token, String key, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            DecodedJWT jwt = JWT.decode(token);
            String value = jwt.getClaim(key).asString();
            return value;
        } catch (JWTDecodeException var6) {
            return null;
        }
    }

    public static String sign(String key, String value, String secret, long expireTime) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        Map<String, Object> header = new HashMap(2);
        header.put("Type", "Jwt");
        header.put("alg", "HS256");
        return JWT.create().withHeader(header).withClaim(key, value).sign(algorithm);
    }

    public static String createToken(AuthUser authUser) {
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        try {
            Algorithm algorithm = Algorithm.HMAC256(ssosecret);
            Builder builder = JWT.create();
            builder.withClaim("data",date);
            builder.withClaim("userId",String.valueOf(authUser.getUserId()));
            builder.withClaim("userName",authUser.getUserName());
            builder.withClaim("userType",String.valueOf(authUser.getUserType()));
            builder.withClaim("phone",authUser.getPhone());
            return builder.sign(algorithm);
        } catch (IllegalArgumentException var7) {
            throw new ServiceException("生成token失败");
        }
    }

    public static String getToken(HttpServletRequest request) {
        String token = request.getHeader("accesstoken");
        log.debug("token-getHeader:" + token);
        if (StringUtil.isNotEmpty(token)) {
            return token;
        } else {
            token = request.getParameter("accesstoken");
            log.debug("token-getParameter:" + token);
            if (StringUtil.isNotEmpty(token)) {
                return token;
            } else {
                token = CookieUtil.getCookie(request, "accesstoken");
                log.debug("token-getCookie:" + token);
                if (StringUtil.isNotEmpty(token)) {
                    return token;
                } else {
                    log.info("accesstoken={}", token);
                    return token;
                }
            }
        }
    }

    private static AuthUser getLocalUser(String tokenId) {
        Object cacheUser = LocalCache.get(tokenId);
        return cacheUser != null && cacheUser instanceof AuthUser ? (AuthUser)cacheUser : null;
    }

    public static void removeLocalUser(String tokenId) {
        log.debug("removeLocalUser={}", tokenId);
        String id = tokenId.replaceAll("\"", "");
        LocalCache.del(id);
        log.debug("LocalCacheget={}", LocalCache.get(id));
    }

    public static AuthUser getUser(HttpServletRequest request) {
        AuthUser user = null;
        try {
            String token = getToken(request);
            AssertUtil.empty(token, TOKEN_EMPTY_MSG, TOKEN_EMPTY);
            user = getUserByToken(token);
        } catch (Exception var4) {
            log.error("验证用户信息失败", var4);
        }

        return user;
    }

    public static AuthUser getUserByToken(String token) {
        if (verify(token, ssosecret)) {
            String userId = JwtUtil.getValue(token, "userId");
            log.debug("tokenId={}", userId);
            AssertUtil.empty(userId, TOKEN_INVALID_MSG, TOKEN_INVALID);
            AuthUser authUser = getLocalUser(userId);
            log.debug("getLocalUser={}", authUser);
            if (StringUtil.isNotNull(authUser)) {
                return authUser;
            }
            try {
                AuthUser ssoAuthUser = new AuthUser();
                String userName = JwtUtil.getValue(token, "userName");
                String userType = JwtUtil.getValue(token, "userType");
                String phone = JwtUtil.getValue(token, "phone");
                ssoAuthUser.setUserId(Long.valueOf(userId));
                ssoAuthUser.setUserName(userName);
                ssoAuthUser.setUserType(Integer.parseInt(userType));
                ssoAuthUser.setPhone(phone);
                //本地缓存
                LocalCache.put(userId, ssoAuthUser);
                return ssoAuthUser;
            } catch (Exception var6) {
                log.error("TOKEN_INVALID_MSG,{}", token);
                throw new ServiceException(TOKEN_INVALID_MSG, TOKEN_INVALID);
            }
        }
        log.error("TOKEN_INVALID_MSG,{}", token);
        throw new ServiceException(TOKEN_INVALID_MSG, TOKEN_INVALID);
    }
}